<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
  <meta name="layout" content="stmain"/>
  <link rel="stylesheet" href="${resource(dir: 'css', file: 'results.css')}" type="text/css"/>
  <link rel="stylesheet" href="${resource(dir: 'css/custom-theme', file: 'jquery-ui-1.8.18.custom.css')}" type="text/css"/>  
  <g:javascript src="jquery-1.7.1.min.js"/>
  <g:javascript src="jquery-ui-1.8.20.custom.min.js"/>
  <g:javascript src="date.format.min.js"/>
  <g:javascript src="highcharts.js"/>
  <g:javascript src="themes/dark-blue.js"/>
  <g:javascript src="graph/resultsgraph.js"/>
  <g:javascript src="dialog.js"/>
  <title>SimTester - Test Results</title>
</head>
<body>
  <h2>Test Results</h2>
  <p id="desc">Test results for ${testrun.name}...</p>
  <div id="graph"></div>
  <div id="chartmenu">
    <span class="statblock">Add these stats:</span>
    <span class="statblock"><input type="checkbox" id="avgresp" name="chartstat" value="avgresp"> <label for="avgresp">Avg. Resp. Time</label></span>
    <span class="statblock"><input type="checkbox" id="rps" name="chartstat" value="rps"/> <label for="rps">RPS</label></span>
    <input class="button green calcbutton" type="button" value="Calculate"/>
    <span class="calcbutton"><g:img dir="images" file="spinner2.gif" style="vertical-align: middle;"/></span>
  </div>
  <div name="status">
  <div name="stats">
    <p id="stat">
      Status: ${testrun.status.capitalize()}<br/>
      Start Date: <g:formatDate date="${testrun.dateCreated}" format="MM/dd/yyyy HH:mm:ss"/><br/>
      End Date: <g:formatDate date="${testrun.endDate}" format="MM/dd/yyyy HH:mm:ss"/><br/>
      <g:set var="trduration" value="${testrun.duration}"/>
      <g:if test="${trduration == -1}">
        Total Duration:<br/>
      </g:if>
      <g:else>
        Total Duration: ${trduration}<br/>
      </g:else>
      <g:if test="${testrun.testDuration}">
        Planned duration: ${testrun.plannedDuration}<br/>
      </g:if>
      <g:else>
      	Number of iterations: ${testrun.repeats}<br/>
      </g:else>
    </p>
  </div>
 <!--
  <div name="stats">
    <p id="stat">
      Status: <span class="det">${testrun.status.capitalize()}</span><br/>
      Start Date: <span class="det"><g:formatDate date="${testrun.dateCreated}" format="MM/dd/yyyy HH:mm:ss"/></span><br/>
      End Date: <span class="det"><g:formatDate date="${testrun.endDate}" format="MM/dd/yyyy HH:mm:ss"/></span><br/>
      <g:set var="trduration" value="${testrun.duration}"/>
      <g:if test="${trduration == -1}">
        Total Duration:<br/>
      </g:if>
      <g:else>
        Total Duration: <span class="det">${trduration}</span><br/>
      </g:else>
      <g:if test="${testrun.testDuration}">
        Planned duration: <span class="det">${testrun.plannedDuration}</span><br/>
      </g:if>
      <g:else>
      	Number of iterations: <span class="det">${testrun.repeats}</span><br/>
      </g:else>
    </p>
  </div>
 -->
  <div id="summary"></div>
  </div>
  <div class="clear"></div>
  <table id="testtable" class="sttable">
    <thead>
      <tr>
        <th>Test Case</th>
        <g:if test="${testrun.type == 'GUI'}">
          <th>Users</th>
        </g:if>
        <th>Progress</th>
        <th> </th>
        <th>Output</th>
        <th>Failures</th>
      </tr>
    </thead>
    <tbody>
      <g:each in="${testcases}" var="tc">
        <tr title="ID: ${tc.id}">
          <td>${tc.name}</td>
          <g:if test="${testrun.type == 'GUI'}">
            <td>${tc.users}</td>
          </g:if>
          <td><div id="prog-${tc.id}"></div></td>
          <td>0%</td>
          <td><a href="javascript:showResultsFor('${tc.id}');">Show all</a></td>
          <td> </td>
        </tr>
      </g:each>
    </tbody>
  </table>
  
  <h3 id="tctitle">Outputs of ${testcases[0].name}</h3>
  <div id="userselect">
    Show the outputs of this user:
    <select>
      <option value="1" selected="selected">1</option>
      <g:if test="${testcases[0].users > 1}">
        <g:each in="${(2..testcases[0].users)}" var="i">
          <option value="${i}">${i}</option>
        </g:each>
      </g:if>
    </select>
  </div>
  <div id="outputcontents">
    <div id="paginate_bar"></div>
    <div id="iterations" class="foldsections"></div>
  </div>
  
  <div id="create-issue-dialog" title="Create Issue">
 
  	 <label>Enter summary and description for this failure</label><br/><br/>
   	 <div>
   	   <label>Summary:</label>
   	   <br/>
   	   <input type="text" id="summary-txt" name="sum" size="52" />
   	 </div>
   	 <br/>
   	 <div>
   	   <label>Priority:</label>
   	 </div>
   	 <div>
   	   <g:select id="bugprioritylist" name="bugprioritylist" from="${['1','2','3','4','5']}" valueMessagePrefix="bug.priority" value="3" />
   	 </div>
   	 <br/>
   	 <div>
   	   <label>Description:</label>
   	   <br/>
   	   <textarea rows="10" cols="58" wrap="off" id="description-txt" name="desc"></textarea>
   	 </div>

  </div>
  
  <g:javascript>
    var sectionsDone = 0;
    var contentData = {};
    var testRunId = '${testrun.id}';
    var testRunType = '${testrun.type}';
    var testCaseId = '${testcases[0].id}';
    var maxSects = 10;
    var currUser = 1;
    var currPage = 1;
    var chartMenuDone = false;
    var remakePaginator = false;
    var queryType = 'outputs';
    
    var sectionsTimer;
    var outputTimers = {};
    
    $('#testtable div[id*="prog-"]')
      .progressbar({value: 1})
      .width(150)
      .find(".ui-progressbar-value").height(20);

    $(document).ready(function() {
      setupChartMenu();
      if(testRunType == 'GUI'){
        var $select = $('#userselect').children('select');
        $select.val(1);
        $select.change(function(){
          refreshOutputs();
        });
      }else{
        $('#userselect').hide();
      }

	  setupGraph(testRunId);
      pollSections(0);
    
    // Create Issue Dialog
      $("#create-issue-dialog").dialog({
        autoOpen: false,
        height: 580,
        width: 550,
        modal: true,
        buttons: [
          {
            id: "create-issue-no",
            text: "Cancel",
            class: 'red button',
            click: function() {
              $(this).dialog("close");
          	}
          },
          {
            id: "create-issue-submit",
            text: "Submit",
            class: 'green button',
            click: function() {
             	var sum =  $("#summary-txt").val();
             	if (!sum) {
             		msgbox("Summary field is required!","warn")
             	} else {
             	
             	var priority = $("#bugprioritylist option:selected").val();
		    	var desc = $("#description-txt").val();
				$.post('/server/testRun/addbugreport/',{ sumtxt:sum , desctxt:desc , priority:priority },function(data){
					if ( data == 'success' ) {
						msgbox("Successfully created a bug report");
					} else {
						var msg = data.result.errors.summary;
						msgbox(msg, "warn");
					}
				});

				$("#summary-txt").val('');
				$("#description-txt").val('');
				$(this).dialog("close");
            	}
            }
          }
        ]
      });
 
    });

    function showResultsFor(tcId){
      testCaseId = tcId;
      var $tcCols = $('#testtable tr[title*="' + tcId + '"] td');
      $('#testtable tr[title!="' + tcId + '"] td').css('backgroundColor', '#B2E3DB');
      $tcCols.css('backgroundColor', '#7FD0C3');

      var name = $tcCols.eq(0).text();
      $('#tctitle').text('Outputs of ' + name);

      if(testRunType == 'GUI'){
        $('#userselect').fadeIn();
        var users = parseInt($tcCols.eq(1).text());
        updUserList(users);
      }
      queryType = 'outputs';
      refreshOutputs();
    }

    function showFailuresFor(tcId){
      $('#userselect').fadeOut();
      
      testCaseId = tcId;
      var $tcCols = $('#testtable tr[title*="' + tcId + '"] td');
      $('#testtable tr[title!="' + tcId + '"] td').css('backgroundColor', '#B2E3DB');
      $tcCols.css('backgroundColor', '#7FD0C3');

      var name = $tcCols.eq(0).text();
      $('#tctitle').text('Failures of ' + name);
      
      queryType = 'failures';
      refreshOutputs();
    }
    
    function refreshOutputs(){
      stopTimers();
      currUser = parseInt($('#userselect').children('select').val());
      $('#outputcontents').fadeTo('fast', 0, function(){
        sectionsDone = 0;
        contentData = {};
        remakePaginator = true;
        gotopage(1);
      });
    }
    
    function updUserList(users){
      var opts = '<option value="1" selected="selected">1</option>';
      if(users > 1){
        var i=0;
        for(i=2;i<=users;i++){
          opts += '<option value="' + i + '">' + i + '</option>';
        }
      }
      $('#userselect select').html(opts);
    }

    function pollSections(time, replace){
      sectionsTimer = setTimeout(function(){
        var startnum = (currPage-1) * maxSects + 1;
        $.getJSON('/server/query/testrunResults/' + testRunId, {trtype: testRunType, type: queryType, tc:testCaseId, user:currUser, num:startnum}, function(data){
          var totalPages = Math.ceil(data.total / maxSects);
          if(data.results.length > 0){
            updatePaginator(totalPages);
            updateIters(data.results, replace);
            updateDash(data.progress);
          }

          if(data.tr.done){
            updateStats(data.tr);
            showSummary();
            if(!chartMenuDone){
              showChartMenu();
            }
          } else {
            pollSections(2000);
          }
        });
      }, time);
    }
    
    function updateDash(progress){
      for(var i in progress){
        // Failures
        var $tcCols = $('#testtable tr[title*="' + progress[i].tc + '"] td');
        if(progress[i].errs > 0){
          var failCol = 4;
          if(testRunType == 'GUI'){
            failCol = 5;
          }
          $tcCols.eq(failCol).html("<a href='javascript:showFailuresFor(\"" + progress[i].tc + "\");'>" + progress[i].errs + " failures</a>");
        }
        
        // Progress
        var progCol = 2;
        if(testRunType == 'GUI'){
          progCol = 3;
        }
        $tcCols.eq(progCol).text(progress[i].prog + '%');
        var prog;
        if(progress[i].prog == 0){
          prog = 1
        } else {
          prog = progress[i].prog
        }
        
        var progbarCol = 1;
        if(testRunType == 'GUI'){
          progbarCol = 2;
        }
        $tcCols.eq(progbarCol).children('div').progressbar({value: prog});
      }
    }

    function showSummary(){
      $.getJSON('/server/query/summary/' + testRunId, function(data){
        var summaryHtml = '<p id="sum"><span id="sumtitle">Summary</span><br/>';
     //   summaryHtml += 'Tests passed:&nbsp;&nbsp;&nbsp;' + data.passed + '/' + data.total + ' (' + (data.passed / data.total * 100).toFixed() + '%)' + '<br/>';
        summaryHtml += 'Tests passed:&nbsp;&nbsp;&nbsp;<span class="det">' + data.passed + '/' + data.total + ' (' + (data.passed / data.total * 100).toFixed() + '%)' + '</span><br/>';
        summaryHtml += 'Total number of requests:&nbsp;&nbsp;&nbsp;<span class="det">' + data.requests + '</span><br/>';
        summaryHtml += 'Peak response time:&nbsp;&nbsp;&nbsp;<span class="det">' + data.peakResp + ' ms</span></p>';
        $('#summary').html(summaryHtml);
      });
    }
    
    function setupChartMenu(){
      $('#chartmenu').hide();
      $('#chartmenu span.calcbutton').hide();
      $('#chartmenu input:button').click(function(){
        var stats = new Array();
        $('input:checkbox[name=chartstat]:checked').filter(':visible').each(function(){
          stats.push($(this));
        });

        if(stats.length > 0){
          showChartMenuSpinner();
          updateChart(stats);
        }
      });
    }
    
    function showChartMenu(){
      $('#chartmenu').fadeIn();
    }
    
    function showChartMenuSpinner(){
      $('#chartmenu input:button').hide();
      $('#chartmenu span.calcbutton').show();
    }
    
    function hideChartMenuSpinner(){
      $('#chartmenu span.calcbutton').hide();
      $('#chartmenu input:button').show();
    }
    
    function updateChart(stats){
      var fadeOutMenu = false;
      if($('input:checkbox[name=chartstat]').filter(':visible').length == stats.length){
        fadeOutMenu = true;
      } else {
        for(var i in stats){
          stats[i].parent().fadeOut();
        }
      }
      
      stats = stats.map(function(x){
        return x.val();
      });

      $.getJSON('/server/query/calcResults/' + testRunId, {stats: stats.join()}, function(data){
        addSeries({rps: data.rps, avgresp: data.avgresp});
        if(data.peakRps){
          $('#summary p').append('<br/>Peak RPS: <span class="det">' + data.peakRps + ' requests/sec</span>');
        }
      })
      .complete(function(){
        if(fadeOutMenu){
          $('#chartmenu').fadeOut();
          chartMenuDone = true;
        }
        hideChartMenuSpinner();
      });
    }
    
    function updatePaginator(total){
      var pagbar = $('#paginate_bar');
      if(remakePaginator || pagbar.children().length == 0){
        remakePaginator = false;
        var pagHtml = '<a href="javascript:pageprev();" class="valigned"><img src="/server/images/prev.png"/></a> Page <select id="pageselect">';
        for(var i=1; i<=parseInt(total); i++){
          pagHtml += '<option value="' + i + '">' + i + '</option>';
        }
        pagHtml += '</select> of <span></span> <a href="javascript:pagenext();" class="valigned"><img src="/server/images/next.png"/></a>';
        pagbar.html(pagHtml);
        pagbar.children('select').change(function(){
          gotopage(parseInt($(this).val()));
        });
      }
      
      if(currPage == 1){
        pagbar.children('a:first').hide();
      } else {
        pagbar.children('a:first').show();
      }

      pagbar.children('select').val(currPage);
      pagbar.children('span').text(total);
      
      if(currPage == total){
        pagbar.children('a:last').hide();
      } else {
        pagbar.children('a:last').show();
      }
    }
    
    function gotopage(page){
      stopTimers();
      currPage = page;
      //updatePaginator($('#paginate_bar').children('span').text());
      refreshPage();
    }
    
    function pageprev(){
      gotopage(currPage-1);
    }
    
    function pagenext(){
      gotopage(currPage+1);
    }
    
    function refreshPage(){
      $('#iterations').fadeTo('fast', 0, function(){
        sectionsDone = 0;
        contentData = {};
        pollSections(0, true);
      });
    }
    
    function stopTimers(){
      clearTimeout(sectionsTimer);
      for(var i in outputTimers){
        clearTimeout(outputTimers[i]);
      }
    }
    
    function updateStats(stats){
      var statsBlock = $('div[name=stats] p');
      var statsStr = statsBlock.html();
      
      // If status is already completed, dont need to update
      if(statsStr.indexOf('Status: Completed') != -1){
        return;
      }
      
      statsStr = statsStr.replace(/Status: \w+/, 'Status: Completed');
      statsStr = statsStr.replace('End Date:', 'End Date: ' + new Date(stats.endDate).format('mm/dd/yyyy HH:MM:ss', true));
      statsStr = statsStr.replace('Total Duration:', 'Total Duration: ' + stats.duration);
      statsBlock.html(statsStr);
    }

    function updateIters(results, replace) {
      var sections = results.length
      var newSections = '';
      var nums = {};

      var sectIds = new Array();
      for(var i=sectionsDone; i < sections; i++) {
        var result = results[i];
        var sectId = sectionId(result.user,result.num);
        sectIds.push(sectId);

        if(!contentData[sectId]){
          contentData[sectId] = {};
          contentData[sectId].outIdx = 0;
          contentData[sectId].polling = 0;
        }
      
        // If section exists
        if($('#sect-' + sectId).length && !replace) {
          updateSection(result);
        } else {
          newSections += createSection(result, sectId);
          
          if(!nums[result.user]){
            nums[result.user] = [];
          }
          nums[result.user].push(result.num);
        }
      }

      if(replace){
        $('#iterations').html(newSections).fadeTo('fast', 1);
        $('#outputcontents').fadeTo('fast', 1);
      } else {
        $('#iterations').append($(newSections).hide().fadeIn());
        for(var i in sectIds){
          $('#sect-' + sectIds[i])
        }
      }
      
      for(var usr in nums){
        var numlist = nums[usr];
        for(var i in numlist){
          (function() {
            var u = usr;
            var num = numlist[i];
            var id = sectionId(u, numlist[i]);

            $('#test-' + id).click(function(){
              pollOutputs(0, $('#cont-' + id + ' pre'), usr, numlist[i]);
            });

            $('#sect-' + id)
              .unbind('click')
              .click(function() {
                toggleOutputs($(this).next().children('pre'), u, num);
                $(this).next().slideToggle('fast');

                return false;
              }).next().hide();
          })();
        }
      }
    };
    
    function sectionId(user, num){
      return user + '-' + num;
    }

    function toggleOutputs(out, user, num) {
      var id = sectionId(user,num);
      
      // Close if visible
      if(out.parent().is(':visible')){
        contentData[id].polling = 0;
      // Show if not visible
      } else {
        if(!contentData[id].polling) {
          contentData[id].polling = 1;
          pollOutputs(0, out, user, num);
        }
      }
    };

    function pollOutputs(time, out, user, num) {
      var id = sectionId(user,num);
      outputTimers[id] = setTimeout(function(){
        $.getJSON('/server/query/outputs/' + testRunId, {tc:testCaseId, user:user, iter:num, min:contentData[id].outIdx}, function(data){
          var x;
          for(x in data.outputs){
            out.append(data.outputs[x] + '\n');
          }
          
          if (data.highestId){
            contentData[id].outIdx = data.highestId + 1;
          }
          
          if(data.done){
            return;
          }
          
          if(contentData[id].polling) {
            pollOutputs(2000, out, user, num);
          }
        });
      }, time);
    };

    function createSection(result, id) {
      var status = 'successful';
      if(result.status == 'failed') {
        status = 'failed';
      } else if(result.status == 'running') {
        status = 'running';
      }

      // Section header
      var sectionText = '<div id="sect-' + id + '" class="section ' + status + ' shadow">';
      sectionText += '<b>User ' + result.user + ' | Test Run ' + result.num + '</b> | ';
      
      var durText = 'Still running';
      if(result.dur != '-1')
        durText = result.dur;
      sectionText += 'Duration: ' + durText;
      sectionText += '</div>';
      
      // Section contents
      sectionText += '<div id="cont-' + id + '" class="section-contents shadow">';
      sectionText += '<a href="/server/testRun/details/' + testRunId + '?tc=' + testCaseId + '&user=' + result.user + '&num=' + result.num + '">View detailed info</a>&nbsp;&nbsp;&nbsp;';   
      sectionText += '<a href="javascript:opencreateissuedialog(\''+id+'\');">Submit Bug Report</a>';
      sectionText += '<input id="test-' + id + '" type="hidden"/>';
      sectionText += '<pre id="results" class="textblock testoutput" name="results">\n';
      sectionText += '</pre></div>';

      return sectionText;
    };

    function updateSection(result) {
      if (result.status == 'running')
        return;

      var status = 'successful';
      if(result.status == 'failed') {
        status = 'failed';
      }
      
      var id = sectionId(result.user,result.num);
      
      // Update header
      $('div#sect-' + id)
        .removeClass('running')
        .addClass(status);

      var sectionText = $('#sect-' + id).html();
      sectionText = sectionText.replace('Still running', result.dur);
      $('#sect-' + id).html(sectionText);
      
      if(testRunType == 'GUI'){
        sectionsDone++;
      }
    };
    
    function opencreateissuedialog(id) {
    	var contId = id;  	
        var desc = "\n\n\n==============================\nDetailed Information\n==============================\n\n" + $('#cont-' + id + ' pre').text();
        $("#description-txt").val(desc);
        $("#create-issue-dialog").dialog("open");
    };
    
  </g:javascript>
</body>
</html>